import { AbsSvgUnitParser } from "../absunitparser"
import pathinfo from "../../../../../canvas/common/struct/basestruct/pathinfo";
import globalconst from "../../../../../canvas/common/globalConst";
var global = globalconst.GlobalConst;
import { SvgPath2InfoSvc } from "./path/svgPath2InfoSvc";
const splitMarkCh = ',';

class PathParser extends AbsSvgUnitParser {
    constructor() {
        super();
        this.type = global.PathType << 16;
        this.pathSecList = [];
        this.secUnitList = [];
    }
    parse(mainEle) {
        let unitInfo = new pathinfo.PathInfo();
        unitInfo.type = this.type;

        const attributes = mainEle.attributes;
        for (let i = 0; i < attributes.length; i++) {
            const attr = attributes[i];
            if (attr.name == 'd') {
                this.parsePoints(attr.value, unitInfo);
            }
        }
        this.parseCommonProp(unitInfo, mainEle);
        if (this.pathSecList.length > 1) {
            let stSec = this.pathSecList[0];
            let nextSec = this.pathSecList[1];
            this.parseSec2Graphs(stSec.param, nextSec, 1);
        }
        console.log(this.secUnitList);
        let pathDesc = SvgPath2InfoSvc.chg2LGXPathGraph(this.secUnitList, this);
        if (!pathDesc || (pathDesc && pathDesc.length.length == 0)){
            unitInfo = null;
        }
        else{
            unitInfo.pathDesc = pathDesc;
        }
        return unitInfo;
    }


    parseSec2Graphs(stPt, curentSec, secIdx) {
        let secType = curentSec.type;
        switch (secType) {
            case 'L':
                this.parseLineSec2Graph(stPt, curentSec, secIdx);
                break;

            case 'A':
                this.parseArcSec2Graph(stPt, curentSec, secIdx);
                break;

            case 'Q':
                this.parseQuadraticSec2Graph(stPt, curentSec, secIdx);
                break;

            case 'C':
                this.parseBezierSec2Graph(stPt, curentSec, secIdx);
                break;
        }
    }

    parseQuadraticSec2Graph(stPt, curentSec, secIdx) {
        let t = { type: 'quadratic', st: stPt, end: curentSec.param };
        this.secUnitList.push(t);

        let nextSec = null;
        if (secIdx + 1 < this.pathSecList.length) {
            nextSec = this.pathSecList[secIdx + 1];
        }
        if (nextSec) {
            this.parseSec2Graphs(curentSec.param, nextSec, secIdx + 1);
        }
    }

    parseBezierSec2Graph(stPt, curentSec, secIdx) {
        let param = { x: 0, y: 0, x1: 0, y1: 0, x2: 0, y2: 0 };
        let x0 = 0;
        let y0 = 0;
        if (curentSec.reletiveCoord) {
            x0 = stPt.x;
            y0 = stPt.y;
        }

        param.x = curentSec.param.x + x0;
        param.y = curentSec.param.y + y0;

        param.x1 = curentSec.param.x1 + x0;
        param.y1 = curentSec.param.y1 + y0;

        param.x2 = curentSec.param.x2 + x0;
        param.y2 = curentSec.param.y2 + y0;

        let t = { type: 'bezier', st: stPt, param };
        this.secUnitList.push(t);

        let nextSec = null;
        if (secIdx + 1 < this.pathSecList.length) {
            nextSec = this.pathSecList[secIdx + 1];
        }
        if (nextSec) {
            let nextStPt = { x: param.x, y: param.y };
            this.parseSec2Graphs(nextStPt, nextSec, secIdx + 1);
        }
    }

    parseLineSec2Graph(stPt, curentSec, secIdx) {
        let x0 = 0;
        let y0 = 0;
        if (curentSec.reletiveCoord) {
            x0 = stPt.x;
            y0 = stPt.y;
        }
        let endx = x0 + curentSec.param.x;
        let endy = y0 + curentSec.param.y;
        let end = {x:endx,y:endy};
        let t = { type: 'line', st: stPt, end };
        this.secUnitList.push(t);

        let nextSec = null;
        if (secIdx + 1 < this.pathSecList.length) {
            nextSec = this.pathSecList[secIdx + 1];
        }
        if (nextSec) {
            this.parseSec2Graphs(end, nextSec, secIdx + 1);
        }
    }

    parseArcSec2Graph(stPt, curentSec, secIdx) {
        let x0 = 0;
        let y0 = 0;
        if (curentSec.reletiveCoord) {
            x0 = stPt.x;
            y0 = stPt.y;
        }

        let rx = curentSec.param.rx;//x和y方向的半径（rx 和 ry）。
        let ry = curentSec.param.ry;
        let angle = curentSec.param.angle;//x轴旋转角度。
        let arcFlag = curentSec.param.arcFlag;//大弧/小弧标志（1表示大弧，0表示小弧）。
        let anticlockwise = curentSec.param.anticlockwise;//顺时针/逆时针标志（0表示顺时针，1表示逆时针）。

        let endx = x0 + curentSec.param.endx;// 弧形终点的坐标
        let endy = y0 + curentSec.param.endy;
        let param = { rx, ry, angle, arcFlag, anticlockwise, endx, endy };

        let t = { type: 'arc', st: stPt, param};
        this.secUnitList.push(t);

        let nextSec = null;
        if (secIdx + 1 < this.pathSecList.length) {
            nextSec = this.pathSecList[secIdx + 1];
        }
        if (nextSec) {
            let nextStPt = { x: endx, y: endy };
            this.parseSec2Graphs(nextStPt, nextSec, secIdx + 1);
        }
    }



    parsePoints(pointStr) {
        let list = pointStr.split('');
        let chCount = pointStr.length;
        let idx = 0;
        do {
            let ch = list[idx];
            if (ch == 'M') {
                idx = this.parsePathStartPoint_relative(idx, list, pointStr, false);
            }
            else if (ch == 'm') {
                idx = this.parsePathStartPoint_relative(idx, list, pointStr, true);
            }
            else {
                idx = this.parsePathSec(ch, idx, list, pointStr);
            }
            idx++;
        }
        while (idx < chCount);
    }

    parsePathStartPoint_relative(idx, list, pointStr, reletiveCoordFlag) {
        let endIdx = this.getSecEndIdx(idx, list);
        let coordStr = pointStr.substring(idx + 1, endIdx + 1);
        coordStr = this.convert2ValidPathCoordStr(coordStr);
        let coordList = coordStr.split(splitMarkCh);
        for (let i = 0; i < coordList.length;) {
            let x = parseFloat(coordList[i++]);
            let y = parseFloat(coordList[i++]);
            let t = { type: 'M', param: { x, y }, reletiveCoord: reletiveCoordFlag };
            this.pathSecList.push(t);
        }
        return endIdx;
    }

    parseLine2Sec_relative(idx, list, pointStr, reletiveCoordFlag) {
        let endIdx = this.getSecEndIdx(idx, list);
        let coordStr = pointStr.substring(idx + 1, endIdx + 1);
        coordStr = this.convert2ValidPathCoordStr(coordStr);
        let coordList = coordStr.split(splitMarkCh);
        for (let i = 0; i < coordList.length;) {
            let x = parseFloat(coordList[i++]);
            let y = parseFloat(coordList[i++]);
            let t = { type: 'L', param: { x, y }, reletiveCoord: reletiveCoordFlag };
            this.pathSecList.push(t);
        }
        return endIdx;
    }

    parseArcSec_relative(idx, list, pointStr, reletiveCoordFlag) {
        let endIdx = this.getSecEndIdx(idx, list);
        let coordStr = pointStr.substring(idx + 1, endIdx + 1);
        coordStr = this.convert2ValidPathCoordStr(coordStr);
        let coordList = coordStr.split(splitMarkCh);
        let i = 0;
        let rx = parseFloat(coordList[i++]);//x和y方向的半径（rx 和 ry）。
        let ry = parseFloat(coordList[i++]);
        let angle = parseFloat(coordList[i++]);//x轴旋转角度。
        let arcFlag = parseInt(coordList[i++]);//大弧/小弧标志（1表示大弧，0表示小弧）。
        let anticlockwise = parseInt(coordList[i++]);//顺时针/逆时针标志（0表示顺时针，1表示逆时针）。

        let endx = parseFloat(coordList[i++]);// 弧形终点的坐标
        let endy = parseFloat(coordList[i++]);
        let param = { rx, ry, angle, arcFlag, anticlockwise, endx, endy };
        let t = { type: 'A', param, reletiveCoord: reletiveCoordFlag };
        this.pathSecList.push(t);
        return endIdx;
    }

    parseBezierSec_relative(idx, list, pointStr, reletiveCoordFlag) {
        let endIdx = this.getSecEndIdx(idx, list);
        let coordStr = pointStr.substring(idx + 1, endIdx + 1);
        coordStr = this.convert2ValidPathCoordStr(coordStr);
        let coordList = coordStr.split(splitMarkCh);
        let i = 0;
        let x1 = parseFloat(coordList[i++]);//控制点1
        let y1 = parseFloat(coordList[i++]);
        let x2 = parseFloat(coordList[i++]);//控制点2
        let y2 = parseFloat(coordList[i++]);

        let x = parseFloat(coordList[i++]);// 目标点
        let y = parseFloat(coordList[i++]);
        let t = { type: 'C', param: { x, y, x1, y1, x2, y2 }, reletiveCoord: reletiveCoordFlag };
        this.pathSecList.push(t);
        return endIdx;
    }

    parsePathSec(secTypeChar, idx, list, pointStr) {
        let parseEndIdx = idx;
        switch (secTypeChar) {
            case 'l'://小写L
                parseEndIdx = this.parseLine2Sec_relative(idx, list, pointStr, true);
                break;

            case 'L':
                parseEndIdx = this.parseLine2Sec_relative(idx, list, pointStr);
                break;

            case 'a':
                parseEndIdx = this.parseArcSec_relative(idx, list, pointStr, true);
                break;

            case 'A':
                parseEndIdx = this.parseArcSec_relative(idx, list, pointStr, false);
                break;

            case 'c':
                parseEndIdx = this.parseBezierSec_relative(idx, list, pointStr, true);
                break;

            case 'C':
                parseEndIdx = this.parseBezierSec_relative(idx, list, pointStr, false);
                break;
        }
        return parseEndIdx;
    }

    getSecEndIdx(idx, list) {
        let dstIdx = list.length - 1;
        for (let i = idx + 1; i < list.length; i++) {
            let char = list[i];
            const codeMethod = char.charCodeAt(0) >= 48 && char.charCodeAt(0) <= 57;
            if (!codeMethod && char != '.' && char != ' ' && char != ',' && char != '-') {
                dstIdx = i - 1;
                break;
            }
        }
        return dstIdx;
    }
}

export { PathParser }